import * as fs from 'fs-extra';
import * as path from 'path';
import {
  IconifyUsageStats,
  IconifyDataOutput,
  IconifyIcon
} from '../types/iconify';

export interface IconifyGeneratorOptions {
  /** 输出目录 */
  outputDir?: string;
  /** 输出文件名 */
  fileName?: string;
  /** 输出格式 */
  format?: 'js' | 'ts' | 'json' | 'imports-only';
  /** 是否生成类型定义 */
  generateTypes?: boolean;
  /** 是否包含统计信息 */
  includeStats?: boolean;
  /** 是否生成 ESM 格式 */
  esm?: boolean;
  /** 压缩输出 */
  minify?: boolean;
  /** 是否生成便捷导入文件 */
  generateImports?: boolean;
}

/**
 * Iconify 数据生成器
 * 将分析结果转换为可引入的数据文件
 */
export class IconifyDataGenerator {
  private defaultOptions: Required<IconifyGeneratorOptions> = {
    outputDir: './data',
    fileName: 'iconify',
    format: 'js',
    generateTypes: true,
    includeStats: true,
    esm: true,
    minify: false,
    generateImports: true
  };

  /**
   * 生成 Iconify 数据文件
   */
  async generate(
    stats: IconifyUsageStats,
    options: IconifyGeneratorOptions = {}
  ): Promise<{ files: string[] }> {
    const opts = { ...this.defaultOptions, ...options };

    // 确保输出目录存在
    await fs.ensureDir(opts.outputDir!);

    const generatedFiles: string[] = [];

    // 生成数据对象
    const data = this.createDataOutput(stats);

    // 根据格式生成文件
    switch (opts.format) {
      case 'imports-only':
        // 只生成便捷导入文件
        generatedFiles.push(
          await this.generateImportsFile(data, opts)
        );
        break;
      case 'js':
        generatedFiles.push(
          await this.generateJavaScriptFile(data, opts),
          ...(opts.esm ? [await this.generateESMFile(data, opts)] : [])
        );
        break;
      case 'ts':
        generatedFiles.push(
          await this.generateTypeScriptFile(data, opts)
        );
        break;
      case 'json':
        generatedFiles.push(
          await this.generateJsonFile(data, opts)
        );
        break;
    }

    // 只有非 imports-only 模式才生成其他文件
    if (opts.format !== 'imports-only') {
      // 生成类型定义文件
      if (opts.generateTypes && opts.format !== 'ts') {
        generatedFiles.push(
          await this.generateTypeDefinitionFile(stats, opts)
        );
      }

      // 生成统计报告
      if (opts.includeStats) {
        generatedFiles.push(
          await this.generateStatsReport(stats, opts)
        );
      }

      // 生成便捷导入文件
      if (opts.generateImports) {
        generatedFiles.push(
          await this.generateImportsFile(data, opts)
        );
      }
    }

    return { files: generatedFiles };
  }

  /**
   * 创建数据输出对象
   */
  private createDataOutput(stats: IconifyUsageStats): IconifyDataOutput {
    const collections: IconifyDataOutput['collections'] = {};

    // 构建集合数据
    for (const [prefix, icons] of stats.collections) {
      collections[prefix] = {
        prefix,
        icons: Array.from(icons).sort(),
        count: icons.size
      };
    }

    // 构建完整图标列表
    const icons = Array.from(stats.icons.keys()).sort();

    return {
      version: '1.0.0',
      generatedAt: new Date().toISOString(),
      collections,
      icons,
      stats: {
        totalIcons: stats.totalIcons,
        totalCollections: stats.collections.size,
        totalUsage: stats.totalUsage,
        filesWithIcons: stats.filesWithIcons
      }
    };
  }

  /**
   * 生成 JavaScript 文件
   */
  private async generateJavaScriptFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}.js`);
    const content = this.formatJavaScript(data, options);

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成 ESM 格式文件
   */
  private async generateESMFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}.mjs`);
    const content = this.formatESM(data, options);

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成 TypeScript 文件
   */
  private async generateTypeScriptFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}.ts`);
    const content = this.formatTypeScript(data, options);

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成 JSON 文件
   */
  private async generateJsonFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}.json`);
    const content = JSON.stringify(data, null, options.minify ? 0 : 2);

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成类型定义文件
   */
  private async generateTypeDefinitionFile(
    stats: IconifyUsageStats,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}.d.ts`);

    const prefixes = Array.from(stats.collections.keys()).sort();
    const allIcons = Array.from(stats.icons.keys()).sort();

    const content = `
// Auto-generated iconify icon types
// Generated at: ${new Date().toISOString()}

export type IconifyPrefix = ${prefixes.map(p => `'${p}'`).join(' | ')};

export type IconifyIcon = ${allIcons.map(icon => `'${icon}'`).join(' | ')};

export interface IconifyCollectionData {
  [key: string]: {
    prefix: string;
    icons: string[];
    count: number;
  };
}

export interface IconifyData {
  version: string;
  generatedAt: string;
  collections: IconifyCollectionData;
  icons: string[];
  stats: {
    totalIcons: number;
    totalCollections: number;
    totalUsage: number;
    filesWithIcons: number;
  };
}

declare const iconifyData: IconifyData;

export default iconifyData;
`.trim();

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成统计报告
   */
  private async generateStatsReport(
    stats: IconifyUsageStats,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}-stats.md`);

    const sortedIcons = Array.from(stats.icons.values())
      .sort((a, b) => b.usageCount - a.usageCount)
      .slice(0, 20); // Top 20

    let content = `# Iconify 图标使用统计报告\n\n`;
    content += `生成时间: ${new Date().toLocaleString()}\n\n`;

    content += `## 总体统计\n\n`;
    content += `- 总图标数量: ${stats.totalIcons}\n`;
    content += `- 图标集合数量: ${stats.collections.size}\n`;
    content += `- 总使用次数: ${stats.totalUsage}\n`;
    content += `- 包含图标的文件数: ${stats.filesWithIcons}/${stats.totalFiles}\n\n`;

    content += `## 图标集合分布\n\n`;
    for (const [prefix, icons] of stats.collections) {
      content += `- **${prefix}**: ${icons.size} 个图标\n`;
    }

    content += `\n## 热门图标 (Top 20)\n\n`;
    content += `| 排名 | 图标名称 | 使用次数 | 使用文件数 |\n`;
    content += `|------|----------|----------|------------|\n`;

    sortedIcons.forEach((icon, index) => {
      content += `| ${index + 1} | \`${icon.name}\` | ${icon.usageCount} | ${icon.files.length} |\n`;
    });

    content += `\n## 完整图标列表\n\n`;
    content += `<!-- 所有使用的图标 -->\n`;
    content += `<!-- 总计: ${stats.totalIcons} 个图标 -->\n\n`;

    for (const [prefix, icons] of stats.collections) {
      content += `### ${prefix}\n\n`;
      const sortedCollection = Array.from(icons).sort();
      for (const icon of sortedCollection) {
        content += `- \`${prefix}:${icon}\`\n`;
      }
      content += '\n';
    }

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 生成便捷导入文件
   */
  private async generateImportsFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): Promise<string> {
    const filePath = path.join(options.outputDir!, `${options.fileName}Imports.js`);
    const content = this.formatImportsFile(data, options);

    await fs.writeFile(filePath, content, 'utf-8');
    return filePath;
  }

  /**
   * 格式化便捷导入文件内容
   */
  private formatImportsFile(
    data: IconifyDataOutput,
    options: Required<IconifyGeneratorOptions>
  ): string {
    const collections = Object.entries(data.collections)
      .sort(([, a], [, b]) => b.count - a.count);

    // 去重并生成 @iconify/json 导入语句
    const uniqueImports = new Map<string, { prefix: string; variableName: string; jsonFileName: string }>();

    collections.forEach(([prefix, collection]) => {
      const jsonFileName = this.getJsonFileName(prefix);
      const variableName = this.getVariableName(prefix, jsonFileName);

      if (!uniqueImports.has(jsonFileName)) {
        uniqueImports.set(jsonFileName, { prefix, variableName, jsonFileName });
      }
    });

    const imports = Array.from(uniqueImports.values())
      .map(({ variableName, jsonFileName }) =>
        `import ${variableName} from '@iconify/json/json/${jsonFileName}.json'`
      ).join('\n');

    // 生成图标集数组
    const iconCollections = Array.from(uniqueImports.values())
      .map(({ variableName }) => `  ${variableName}`)
      .join(',\n');

    // 生成注释信息
    const collectionComments = collections.map(([prefix, collection]) => {
      const jsonFileName = this.getJsonFileName(prefix);
      const variableName = this.getVariableName(prefix, jsonFileName);
      return `// ${prefix} - ${collection.count} 个图标`;
    }).join('\n');

    return `/**
 * Iconify 图标集注册文件
 * 生成时间: ${data.generatedAt}
 *
 * 分析结果：
 * - 总图标数量: ${data.stats.totalIcons}
 * - 图标集合数量: ${data.stats.totalCollections}
 * - 总使用次数: ${data.stats.totalUsage}
 * - 涉及文件数: ${data.stats.filesWithIcons}
 *
 * 使用方法:
 * 1. 将此文件导入到你的应用入口文件
 * 2. 确保已安装依赖: @iconify/vue @iconify/json
 * 3. 所有图标集将自动注册到全局
 */

import { addCollection } from '@iconify/vue'

${collectionComments}

${imports}

/**
 * 项目中使用的图标集数据
 */
const iconCollections = [
${iconCollections}
]

/**
 * 全局注册图标集数据 - 实现完全本地化
 *
 * 这将注册所有项目使用的图标集到 Iconify Vue 组件中
 * 注册后，你可以直接在组件中使用任何图标，无需额外导入
 */
iconCollections.forEach(iconSet => {
  addCollection(iconSet)
})

/**
 * 获取已注册的图标集信息
 */
export const registeredCollections = iconCollections.map(iconSet => ({
  prefix: iconSet.prefix || iconSet.info?.prefix,
  name: iconSet.info?.name || iconSet.prefix,
  total: Object.keys(iconSet.icons || {}).length
}))

/**
 * 便利方法
 */
export const getRegisteredCollections = () => registeredCollections

export const hasCollection = (prefix) => {
  return registeredCollections.some(col => col.prefix === prefix)
}

/**
 * 导出注册统计信息
 */
export const stats = {
  totalIcons: ${data.stats.totalIcons},
  totalCollections: ${data.stats.totalCollections},
  totalUsage: ${data.stats.totalUsage},
  filesWithIcons: ${data.stats.filesWithIcons},
  generatedAt: '${data.generatedAt}'
}

// 默认导出
export default {
  collections: iconCollections,
  registeredCollections,
  stats,
  getRegisteredCollections,
  hasCollection
}`;
  }

  /**
   * 获取 @iconify/json 中的文件名
   */
  private getJsonFileName(prefix: string): string {
    // 特殊映射关系
    const specialMappings: Record<string, string> = {
      'icon-park-outline': 'icon-park',
      'icon-park-solid': 'icon-park',
      'fluent-emoji-high-contrast': 'fluent-emoji',
      'material-symbols-light': 'material-symbols',
      'simple-line-icons': 'simple-line-icons',
      'fa-regular': 'fa',
      'pepicons-pop': 'pepicons',
      'system-uicons': 'system-uicons'
    };

    return specialMappings[prefix] || prefix;
  }

  /**
   * 获取变量名
   */
  private getVariableName(prefix: string, jsonFileName?: string): string {
    const fileName = jsonFileName || this.getJsonFileName(prefix);

    // 特殊映射 - 根据实际 JSON 文件名生成变量名
    const specialMappings: Record<string, string> = {
      'icon-park': 'iconParkIcons',
      'fluent-emoji': 'fluentEmojiIcons',
      'material-symbols': 'materialSymbolsIcons',
      'simple-line-icons': 'simpleLineIcons',
      'fa': 'faIcons',
      'pepicons': 'pepiconsIcons',
      'system-uicons': 'systemUiconsIcons'
    };

    if (specialMappings[fileName]) {
      return specialMappings[fileName];
    }

    // 转换为驼峰命名
    const camelCase = fileName.split(/[-_]/)
      .map((word, index) => index === 0 ? word :
           word.charAt(0).toUpperCase() + word.slice(1))
      .join('');

    return `${camelCase}Icons`;
  }

  /**
   * 格式化 JavaScript 代码
   */
  private formatJavaScript(data: IconifyDataOutput, options: Required<IconifyGeneratorOptions>): string {
    const dataStr = JSON.stringify(data, null, options.minify ? 0 : 2);

    return `/**
 * Iconify 图标数据
 * 生成时间: ${data.generatedAt}
 *
 * 使用方法:
 * const iconData = require('./${options.fileName}.js');
 *
 * // 获取所有图标
 * const allIcons = iconData.icons;
 *
 * // 获取特定集合的图标
 * const mdiIcons = iconData.collections.mdi?.icons || [];
 */

(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  typeof define === 'function' && define.amd ? define(factory) :
  (global = global || self, global.${options.fileName} = factory());
}(this, (function () { 'use strict';

  const data = ${dataStr};

  // 便利方法
  data.getIcons = function(prefix) {
    return this.collections[prefix]?.icons || [];
  };

  data.hasIcon = function(iconName) {
    return this.icons.includes(iconName);
  };

  data.getPrefixes = function() {
    return Object.keys(this.collections);
  };

  return data;

})));`;
  }

  /**
   * 格式化 ESM 代码
   */
  private formatESM(data: IconifyDataOutput, options: Required<IconifyGeneratorOptions>): string {
    const dataStr = JSON.stringify(data, null, options.minify ? 0 : 2);

    return `/**
 * Iconify 图标数据 (ESM)
 * 生成时间: ${data.generatedAt}
 *
 * 使用方法:
 * import iconData from './${options.fileName}.mjs';
 *
 * // 获取所有图标
 * const allIcons = iconData.icons;
 *
 * // 获取特定集合的图标
 * const mdiIcons = iconData.collections.mdi?.icons || [];
 */

const data = ${dataStr};

// 便利方法
data.getIcons = function(prefix) {
  return this.collections[prefix]?.icons || [];
};

data.hasIcon = function(iconName) {
  return this.icons.includes(iconName);
};

data.getPrefixes = function() {
  return Object.keys(this.collections);
};

export default data;
export { data as iconifyData };`;
  }

  /**
   * 格式化 TypeScript 代码
   */
  private formatTypeScript(data: IconifyDataOutput, options: Required<IconifyGeneratorOptions>): string {
    const dataStr = JSON.stringify(data, null, options.minify ? 0 : 2);

    return `/**
 * Iconify 图标数据 (TypeScript)
 * 生成时间: ${data.generatedAt}
 *
 * 使用方法:
 * import iconData from './${options.fileName}';
 *
 * // 获取所有图标
 * const allIcons: string[] = iconData.icons;
 *
 * // 获取特定集合的图标
 * const mdiIcons: string[] = iconData.collections.mdi?.icons || [];
 */

import type { IconifyData } from './types/iconify';

const data: IconifyData = ${dataStr};

// 便利方法
data.getIcons = function(prefix: string): string[] {
  return this.collections[prefix]?.icons || [];
};

data.hasIcon = function(iconName: string): boolean {
  return this.icons.includes(iconName);
};

data.getPrefixes = function(): string[] {
  return Object.keys(this.collections);
};

export default data;
export { data as iconifyData };
export type { IconifyData };`;
  }
}